#!/bin/bash

# chroot_kernel_guard: Guards against not being able to reboot the computer
#                      because the kernel has changed and calls to reboot(8)
#                      fail.

# Requires an applicable transcript to be passed in as $1.

# Uses the following tools:
#  /bin/bash
#  /bin/sh
#  /bin/ps
#  /sbin/reboot
#  /usr/bin/grep

# And the following for chroot:
#  /usr/lib/dyld
#  /usr/lib/system/libmathCommon.A.dylib

# Uses otool if available.

. /etc/radmind.defaults

# Declarations
CHROOT_SCRIPT="/private/etc/hooks/chroot_reboot"
CHROOT_SPACE="/tmp/.chroot.$$"
TOOL_LIST="/bin/bash /bin/sh /bin/ps /sbin/reboot /usr/bin/grep /bin/sleep \
	   /bin/test"

# These will eventually hold more, but are initialized with default values.
dependencyList="/usr/lib/dyld /usr/lib/system/libmathCommon.A.dylib"
searchList="/mach_kernel"

# If otool exists, use that to dynamically generate a list of dependencies; use
# a pre-made list if it doesn't.
if /bin/test -x "/usr/bin/otool"; then
	for x in ${TOOL_LIST}; do
		for y in $(otool -LX $x | awk '{ print $1 }'); do
			dependencyList="${dependencyList} $y";
		done;
	done
else
	dependencyList="/usr/lib/dyld \
			/usr/lib/libgcc_s.1.dylib \
			/usr/lib/libiconv.2.dylib \
		    /usr/lib/libncurses.5.4.dylib \
			/usr/lib/libSystem.B.dylib \
			/usr/lib/system/libmathCommon.A.dylib"
fi

for x in $(for y in ${TOOL_LIST} ${dependencyList}; do echo $y; done | \
	   sort --ignore-case --unique); do
	searchList="${searchList} $x";
done

/bin/echo ${searchList} | sort --unique --ignore-case | while read line; do
	if /bin/test -n "$(grep ${line} "${1}")"; then # match found
		touch "${CHROOT_FLAG}"

		# Copy everything into the chroot space.
		mkdir -p ${CHROOT_SPACE}/usr/lib/system
		mkdir -p ${CHROOT_SPACE}/bin
		mkdir -p ${CHROOT_SPACE}/sbin
		mkdir -p ${CHROOT_SPACE}/usr/bin

		for x in ${searchList}; do
			ditto $x ${CHROOT_SPACE}$x
		done

		cp "${CHROOT_SCRIPT}" "${CHROOT_SPACE}"

		# Hand off to the chroot space
		shortName="$(echo "${CHROOT_SCRIPT}" | awk -F '/' '{ print $NF }')"

		/usr/sbin/chroot "${CHROOT_SPACE}" "./${shortName}" &
		exit 0
	fi
done
